package com.gotokeep.keep.composition.demo.samples;

import android.Manifest;
import android.app.ProgressDialog;
import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.TextureView;
import android.widget.TextView;

import com.afollestad.materialdialogs.MaterialDialog;
import com.gotokeep.keep.composition.demo.R;
import com.gotokeep.keep.composition.demo.internal.TransitionRenderThread;
import com.gotokeep.keep.composition.demo.renderer.TransitionRender;
import com.gotokeep.keep.composition.demo.source.SourceProvider;
import com.gotokeep.keep.composition.demo.widgets.ScalableTextureView;

import java.io.File;
import java.util.concurrent.atomic.AtomicBoolean;

public class TransitionActivity extends AppCompatActivity
        implements TextureView.SurfaceTextureListener,
        TransitionRenderThread.RenderListener, Handler.Callback{

    private static final String TAG = TransitionActivity.class.getSimpleName();
    private ScalableTextureView previewView;
    private TextView timeView;
    private long time = 0;
    private long timeUs = 0;
    private int frameCount = 0;
    private long frameCountTime = 0;
    private float fps = 0;
    private boolean export = false;
    private MaterialDialog dialog = null;
    private Handler handler;

    private TransitionRenderThread composerThread = null;
    private TransitionRender renderer = null;
    //    private SpeedPlayThread playThread = null;
    private AtomicBoolean shouldRender = new AtomicBoolean(true);
    private TimeRunnable timeRunnable = new TimeRunnable();

    private static final float speed = 3.0f;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fast_play);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, 0);
        }
        handler = new Handler(this);
        timeView = findViewById(R.id.time);
        previewView = findViewById(R.id.preview_view);

        renderer = new TransitionRender(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_composition, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_play:
                previewView.setSurfaceTextureListener(this);
                if (previewView.isAvailable()) {
                    renderer.setViewport(previewView.getWidth(), previewView.getHeight());
                    startPlay(previewView.getSurfaceTexture());

                }
                return true;
            case R.id.action_export:
                renderer.setViewport(previewView.getWidth(), previewView.getHeight());
                export();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void export() {
        String filePath[] = new String[] {
                SourceProvider.VIDEO_SRC[0], SourceProvider.VIDEO_SRC[1]
        };
        export = true;
        renderer.setViewport(960, 540);
        composerThread = new TransitionRenderThread(filePath, SourceProvider.OUTPUT_PATH[0],
                null, renderer, shouldRender, speed, handler);
        composerThread.setRenderListener(this);
        composerThread.setExport(true);
        composerThread.start();
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        Log.d(TAG, String.format("onSurfaceTextureAvailable: w: %d, h: %d", width, height));
        renderer.setViewport(width, height);
        startPlay(surface);
//        playThread = new SpeedPlayThread(SourceProvider.VIDEO_SRC[0], shouldRender, speed);
//        playThread.start();
    }

    private void startPlay(SurfaceTexture surface) {
        String filePath[] = new String[] {
                SourceProvider.VIDEO_SRC[0], SourceProvider.VIDEO_SRC[1]
        };
        File file = new File(SourceProvider.OUTPUT_PATH[0]);
        if (file.exists()) {
            file.delete();
        }
        export = false;
        composerThread = new TransitionRenderThread(filePath, SourceProvider.OUTPUT_PATH[0],
                surface, renderer, shouldRender, speed, handler);
        composerThread.setRenderListener(this);
        composerThread.start();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        renderer.setViewport(width, height);
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        shouldRender.set(false);
        composerThread = null;
        timeView.removeCallbacks(timeRunnable);
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    @Override
    public void onVideoSizeChanged(int width, int height, int rotation) {
        if (rotation % 180 == 90) {
            int t = width;
            width = height;
            height = t;
        }
        renderer.setVideoSize(width, height);
        final int finalWidth = width;
        final int finalHeight = height;
        previewView.post(() -> previewView.setVideoSize(finalWidth, finalHeight, 0));
    }

    @Override
    public void onVideoEnd() {
        Log.d(TAG, "onVideoEnd: ");
        timeView.removeCallbacks(timeRunnable);
        if (dialog != null) {
            dialog.dismiss();
        }
    }

    @Override
    public void onFrameTime(long timeUs) {
        this.timeUs = timeUs;
        frameCount += 1;
    }

    @Override
    public void onFirstFrameRendered() {
        Log.d(TAG, "onFirstFrameRendered: ");
        timeRunnable.startMs = SystemClock.elapsedRealtime();
        timeView.post(timeRunnable);
        if (export) {
            handler.post(() -> dialog = new MaterialDialog.Builder(this)
                    .content("导出中……")
                    .show());
        }
    }

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_VIDEO_SIZE_CHANGE:
                TransitionRenderThread.VideoSizeInfo info = (TransitionRenderThread.VideoSizeInfo) msg.obj;
                onVideoSizeChanged(info.width, info.height, info.rotation);
                break;
            case MSG_VIDEO_END:
                onVideoEnd();
                break;
            case MSG_FIRST_FRAME_RENDERED:
                onFirstFrameRendered();
                break;
            case MSG_FRAME_TIME:
                onFrameTime((Long) msg.obj);
                break;
        }
        return false;
    }

    private class TimeRunnable implements Runnable {
        long startMs;
        @Override
        public void run() {
            long time = SystemClock.elapsedRealtime() - startMs;
            long t = timeUs / 1000;
            if (time - frameCountTime > 1000) {
                frameCountTime = time;
                fps = frameCount;
                frameCount = 0;
            }
            timeView.setText(String.format("00:00:%02d.%03d\n00:00:%02d.%03d\nfps=%.1f/s", time / 1000, time % 1000,
                    t / 1000, t % 1000, fps));
            timeView.postOnAnimation(this);
//            if (dialog != null) {
//                dialog.setContent(String.format("导出时间进度：00:00:%02d.%03d", t / 1000, t % 1000));
//            }
        }
    }
}
